package com.sora.sora.message.service.impl;

import com.sora.sora.common.constant.ResultCode;
import com.sora.sora.common.exception.ApiException;
import com.sora.sora.common.utils.StringUtils;
import com.sora.sora.message.mapper.EmailMapper;
import com.sora.sora.message.service.MailService;
import com.sora.sora.security.login.mapper.LoginMapper;
import com.sora.sora.security.login.model.bo.verify.CodeFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("mailService")
public class MailServiceImpl implements MailService {

    @Resource
    JavaMailSenderImpl javaMailSender;

    @Resource
    EmailMapper emailMapper;

    @Resource
    LoginMapper loginMapper;

    @Resource
    RedisTemplate<String, String> redisTemplate;

    @Resource
    StringUtils stringUtils;

    @Resource
    CodeFactory codeFactory;

    @Value("${spring.mail.username}")
    String sender;


    @Override
    public boolean emailExist(String email) {
        return loginMapper.queryNameByEmail(email) != null;
    }

    @Override
    public boolean findPassword(String email, String sessionId) {
        int time = 5;
        Duration expire = Duration.ofMinutes(time);
        String code = codeFactory.getNumberCode().value();
        String title = "【Teil】找回密码";
        String content = "您正在找回密码！验证码如下：" + code + "，有效期为" + time + "分钟";
        if (Boolean.TRUE.equals(redisTemplate.hasKey(sessionId))) {
            redisTemplate.opsForValue().set(email, code, expire);
            sendEmail(sender, email, title, content);
            return true;
        }
        return false;
    }

    @Override
    public boolean register(String recipient, String sessionId) {
        int time = 5;
        Duration expire = Duration.ofMinutes(time);
        String code = codeFactory.getLetterNumberMixCode().value();
        String title = "【Teio】欢迎注册！";
        String content = "您的验证码如下：" + code + "，有效期为"+ time + "分钟";
        if (Boolean.TRUE.equals(redisTemplate.hasKey(sessionId))) {
            redisTemplate.opsForValue().set(recipient, code, expire);
            sendEmail(this.sender, recipient, title, content);
            return true;
        }
        return false;
    }

    @Override
    public boolean register(String recipient) {
        int time = 5;
        Duration expire = Duration.ofMinutes(time);
        String code = codeFactory.getLetterNumberMixCode().value();
        String title = "【Teio】欢迎注册！";
        String content = "您的验证码如下：" + code + "，有效期为"+ time + "分钟";
        redisTemplate.opsForValue().set(recipient, code, expire);
        sendEmail(this.sender, recipient, title, content);
        return true;
    }

    @Override
    public boolean infoPasswordChange(String email) {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        String title = "【Teio】密码变更通知";
        String content = "您的账号于" + simpleDateFormat.format(date) + "修改密码，如非本人操作，请尽快更换账号密码和邮箱密码";
        int i = sendEmail(sender, email, title, content);
        return i > 0;
    }

    @Override
    public boolean infoPasswordChange(int uid) {
        String email = emailMapper.queryEmailById(uid);
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        String title = "【Teio】密码变更通知";
        String content = "您的账号于" + simpleDateFormat.format(date) + "修改密码，如非本人操作，请尽快更换账号密码和邮箱密码";
        int i = sendEmail(sender, email, title, content);
        return i > 0;
    }

    @Override
    public boolean infoEmailChange(int uid, String oldEmail) {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        String title = "【Teio】邮箱变更通知";
        String content = "您的账号于" + simpleDateFormat.format(date) + "修改邮箱，如非本人操作，请尽快更换账号密码和邮箱密码";
        int i = sendEmail(sender, oldEmail, title, content);
        return i > 0;
    }

    @Override
    public int sendEmail(String sender, Integer uid, String title, String content) {
        List<Integer> list = new ArrayList<>();
        list.add(uid);
        return sendEmail(sender, list, title, content);
    }

    @Override
    public int sendEmail(String sender, List<Integer> recipient, String title, String content) {

        if (stringUtils.isBlank(title)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "邮件标题不能为空");
        } else if (stringUtils.isBlank(content)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "邮件内容不能为空");
        } else if (stringUtils.isBlank(sender)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "发信人不能为空");
        } else if (recipient == null || recipient.isEmpty()) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "收信人不能为空");
        }

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(sender);
        message.setSubject(title);
        message.setText(content);
        for (Integer uid : recipient) {
            System.out.println(emailMapper.equals(uid));
            message.setTo(emailMapper.queryEmailById(uid));
            javaMailSender.send(message);
        }

        return 1;
    }

    @Override
    public int sendEmail(String sender, String recipient, String title, String content) {

        if (stringUtils.isBlank(title)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "邮件标题不能为空");
        } else if (stringUtils.isBlank(content)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "邮件内容不能为空");
        } else if (stringUtils.isBlank(sender)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "发信人不能为空");
        } else if (stringUtils.isBlank(recipient)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "收信人不能为空");
        }

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(sender);
        message.setSubject(title);
        message.setText(content);
        message.setTo(recipient);

        javaMailSender.send(message);
        return 1;
    }


    @Override
    public int sendEmail(String sender, List<Integer> recipient, String title, String content, Map<String, File> map ,String encode) throws MessagingException {

        if (stringUtils.isBlank(sender)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "发信人不能为空");
        } else if (stringUtils.isBlank(title)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "邮件标题不能为空");
        } else if (stringUtils.isBlank(content)) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "邮件内容不能为空");
        } else if (recipient == null || recipient.isEmpty()) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "收信人不能为空");
        } else if (map == null || map.isEmpty()) {
            throw new ApiException(ResultCode.VALIDATE_FAILED, "文件名不能为空");
        }

        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true, encode);

        helper.setFrom(sender);
        helper.setSubject(title);
        helper.setText(content);

        for (String key : map.keySet()) {
            helper.addAttachment(key, map.get(key));
        }

        for (Integer uid : recipient) {
            helper.setTo(emailMapper.queryEmailById(uid));
            javaMailSender.send(message);
        }

        return 1;
    }

    @Override
    public int sendEmail(String sender, List<Integer> recipient, String title, String content, Map<String, File> map) throws MessagingException {
        return sendEmail(sender, recipient, title, content, map, null);
    }
}
